package weeny.recycle;

import java.io.InputStream;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import prefuse.data.Graph;
import prefuse.data.io.DataIOException;
import prefuse.data.parser.DataParseException;
import prefuse.util.TypeLib;

@Deprecated
public class MoreGraphReader extends ArraySupportedGraphReader{
	public Graph safeRead(String file){
		try {
			Graph graph = readGraph(file);
			return graph;
		} catch (DataIOException e) {
			e.printStackTrace();
		}
		return null;
	}
    public Graph readGraph(InputStream is) throws DataIOException {
        try {       
            SAXParserFactory factory   = SAXParserFactory.newInstance();
            SAXParser        saxParser = factory.newSAXParser();
            
            GraphMLHandler   handler   = new MoreGraphMLHandler();
            saxParser.parse(is, handler);
            return handler.getGraph();
        } catch ( Exception e ) {
            if ( e instanceof DataIOException ) {
                throw (DataIOException)e;
            } else {
                throw new DataIOException(e);
            }
        }
    }
    public static class MoreGraphMLHandler extends GraphMLHandler{
		public MoreGraphMLHandler() {
			super(null,null);
		}
		private Class elemType = null;
		protected Class parseType(String type) {
			try{
				elemType = null;
				return super.parseType(type);
			}
			catch (Exception e) {
			}
			try {
				if (type.contains(":")) {
					String[] tokens = type.split(":");
					elemType = Class.forName(tokens[1]);
					return Class.forName(tokens[0]);
				}
				else{
					elemType = null;
					return Class.forName(type);
				}
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			}
			error("Unrecognized data type: "+type);
            return null;
		}
		protected Map<String, Class> field2ElemType = new HashMap<String, Class>();
		protected void addToSchema() {
			if ( m_name == null || m_name.length() == 0 )
                error("Empty "+KEY+" name.");
            if ( m_type == null || m_type.length() == 0 )
                error("Empty "+KEY+" type.");
            
            try {
                Class typeInFile = parseType(m_type);
                if (elemType != null) {
					field2ElemType.put(m_name, elemType);
				}
                Object dflt = m_dflt==null ? null : parse(m_dflt, typeInFile);
                if ( m_for == null || m_for.equals(ALL) || m_for.equals(NODE) ) {
            		if (Collection.class.isAssignableFrom(typeInFile)) {
            			name2OldType.put(m_name, String[].class);
            		}
                    m_nsch.addColumn(m_name, typeInFile, dflt);
                } 
                if ( m_for == null || m_for.equals(ALL) || m_for.equals(EDGE) ) {
                	if (Collection.class.isAssignableFrom(typeInFile)) {
                		name2OldType.put(m_name, String[].class);
            		}
                    m_esch.addColumn(m_name, typeInFile, dflt);
                } 
                else if ( m_for != null && !m_for.equals(ALL) && !m_for.equals(EDGE) && !m_for.equals(NODE)){
                    error("Unrecognized \""+FOR+"\" value: "+ m_for);
                }
                m_idMap.put(m_id, m_name);
                
                m_dflt = null;
            } catch ( DataParseException dpe ) {
                error(dpe);
            }
		}
    
		protected Object getValue(String name, String value, Class tableType) throws DataParseException{
        	if (value.equals("null")) {
				return null;
			}
        	if (!name2OldType.containsKey(name)) {
        		if (ObjectParser.class.isAssignableFrom(tableType)) {
					try {
						return ((ObjectParser)tableType.newInstance()).decode(value);
					} catch (Exception e) {
						throw new RuntimeException(e);
					}
				}
        		else if (ObjectParserFactory.contains(tableType)){
        			return ObjectParserFactory.get(tableType).decode(value);
        		}
        		else
        			return parse(value, tableType);
			}
        	else{
        		//tableType here is the target type we want to store those arrays
        		String[] val = (String[]) parse(value, name2OldType.get(name));
        		Collection obj = null;
				try {
					obj = (Collection) tableType.newInstance();
				} catch (Exception e) {
					e.printStackTrace();
				}
				if (val.length>0) {
					Class elemType = field2ElemType.get(name);
					Class primitive = null;
					ObjectParser parser = null;
					ObjectParser elemInst = null;
					if (Number.class.isAssignableFrom(elemType))
						primitive = TypeLib.getPrimitiveType(elemType);
					else if (ObjectParserFactory.contains(elemType))
						parser = ObjectParserFactory.get(elemType);
					else if (ObjectParser.class.isAssignableFrom(elemType)) {
						try {
							elemInst = (ObjectParser) elemType.newInstance();
							ObjectParserFactory.put(elemType, elemInst);
						} catch (Exception e) {
							e.printStackTrace();
						}
					}
					
					for (int i = 0; i<val.length; i++){
						if (elemType.equals(String.class)){
							obj.add(val[i]);
						}
						else if (primitive != null) {
							obj.add(parse(val[i], primitive));
						}
						else if (parser != null){
							obj.add(parser.decode(val[i]));
						}
						else{//elemInst should not be null
							obj.add(elemInst.decode(val[i]));
						}
					}
				}
        		return obj;
        	}
        }
		public static Collection collection(Class bagType, Class elemType, String value){
	    	//tableType here is the target type we want to store those arrays
	    	List<String> list = csvStringList(value);
	    	String[] val = list.toArray(new String[0]);
			Collection obj = null;
			try {
				obj = (Collection) bagType.newInstance();
			} catch (Exception ep) {
				ep.printStackTrace();
			}
			if (val.length>0) {
				Class primitive = null;
				ObjectParser parser = null;
				ObjectParser elemInst = null;
				if (Number.class.isAssignableFrom(elemType))
					primitive = TypeLib.getPrimitiveType(elemType);
				else if (ObjectParserFactory.contains(elemType))
					parser = ObjectParserFactory.get(elemType);
				else if (ObjectParser.class.isAssignableFrom(elemType)) {
					try {
						elemInst = (ObjectParser) elemType.newInstance();
						ObjectParserFactory.put(elemType, elemInst);
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
				
				for (int i = 0; i<val.length; i++){
					if (elemType.equals(String.class)){
						obj.add(val[i]);
					}
					else if (primitive != null) {
						try {
							obj.add(parse(val[i], primitive));
						} catch (DataParseException e) {
							e.printStackTrace();
						}
					}
					else if (parser != null){
						obj.add(parser.decode(val[i]));
					}
					else{//elemInst should not be null
						obj.add(elemInst.decode(val[i]));
					}
				}
			}
			return obj;
	    }
    }
    
    
    public static void main(String[] args) {
//		MoreGraphReader reader = new MoreGraphReader();
//		try {
//			Graph g = reader.readGraph(Control.desktopFolder()+"ttt.xml");
//			new MoreGraphWriter().writeGraph(g, Control.desktopFolder()+"new.xml");
//			System.out.println(g.getNodeTable().getSchema());
//			System.out.println(g.getEdgeTable().getSchema());
//		} catch (DataIOException e) {
//			e.printStackTrace();
//		};
//		JSONObject obj = new JSONObject(StrokeLib.getStroke(1), true);
//		Counter cc = new Counter();
//		cc.increase("Acd");
//		cc.increase("ww\"",10.3);
//		obj = new JSONObject(cc.cnt);
////		obj.stringToValue(s)
//		System.out.println(obj.toString());
	}
}